在軟體設計有個 『 SOLID 原則 』的幾個原則,它是由 5 個原則所組成,而這 5 個原則所想要達的的事情為以下兩點 :
接下來這篇文章我們將要談談第一個原則 SRP 單一職責原則
SRP 單一職責原則,最一開始是由一位叫 Robert Cecil Martin 在他的 《敏捷軟體開發,原則,模式和實踐》一書中所提到的『 物件導向設計原則 』
一個 『 類別 』只對一個『 原因 』引起變化 ( A class should have only one reason to change )
然後這位作者在之後出版的一本書《 Clean Architecture 》又將定義修改成如下 :
一個 『 類別 』只有一個『 角色 』引起『 變化 』
那這一個『 角色 』指的是什麼呢 ? 而 『 變化 』 又是什麼呢 ? 我這裡自已的想法為 :
『 角色 』代表這個類別的使用者 ( 想成實體化後執行方法的地方 ),而『 變化 』代表『 因為這角色某個需求,而需要去修改程式碼。
然後 DDD 裡面有提到的 Context 概念,我也覺得很符合 SRP 想表達的觀念。
上面這句話,我們接下來用下面的範例,來簡單說明。
假設我們有個類別,計算直播的觀看數,就是簡單的去資料庫拿資料 ( 這只是範例,我知道有些情況不適合去 DB 拿這個數字 )。
// Bad SRP
class LiveViewCountCalculator{
constructor(){
// 假設每個筆單只有一種類型的產品
}
calcFee(){
let viewCount = 0
viewCount = await _getViewCountFromDB()
return viewCount
}
}
然後目前會使用這個方法的兩種角色『 前台給觀眾看 』、『 後台給直播主、工作人觀看 』,在需求沒有變動的情況下沒什麼問題。
但如果這時前台給觀眾看的決定灌水怎麼辦呢 ?
如果這時改了,『 就同時會影響到後台給直播主看的實際數字 』,所以如果修改成如下會比較好點,根據『 角色 』來拆,這樣一個角色的改變,就不會影響到另一個角色。
// Good SRP
class AdminLiveViewCountCalculator{
calcFee(){
let viewCount = 0
viewCount = await _getViewCountFromDB()
return viewCount
}
}
class GeneralLiveViewCountCalculator{
calcFee(){
let viewCount = 0
viewCount = await _getViewCountFromDB()
return viewCount * 2
}
}
然後上述的範例是以『 角色 』為概念來取分,但是在 DDD 中它還會在用 Context 來取分,以上述的範例你可以『 直播前台直播中、直播前台直播結束、後台直播時 』這樣分 context 的情況下,更能預防因為 context 情況變而所需要的調整。
事實上是不一定,在《敏捷軟體開發,原則,模式和實踐》裡有提到 :
If the application changes in ways that affect the signature of the connection functions, then the design will smell of Rigidity... In that case the two responsibilities should be separated. If, on the other hand, the application is not changing in ways that cause the two responsibilities to change at different times, then there is no need to separate them.
這個是我自已的理解的想法,如果每一次的改動對不同的角色事實上都是連動的,那就沒必要拆開,而如果是一個角色動,會影響到另一個角色使用,則拆。
SRP 單一職則原則,雖然定義上為如下,但事實上我覺得還有很多東西也適合這個原則。
一個 『 類別 』只有一個『 角色 』引起『 變化 』
像是在《 架構師的自我修鍊中 》有提到建議一個實踐 :
一個 class or function 打開來以後,不要超過一個螢幕
我覺得這是個不錯的建議,畢竟一個太長的 class 或 function 雖然不能說是一定,但基本上就有一定等級的壞味道,可以考慮往不同角色用他的情況,會不會世界炸掉。
下面這一段是我最近從某個 youtbue 上看到的學到的方法,也就是每一次學習完,問這三個問題,就可以加深記憶,對我這種老人腦袋 ~ 希望有點幫助
記憶中和 clear code 這本書中有提到,一個方法只做一件事情,這點我覺得也算是 SRP 原則